package com.google.srclib.stock;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import com.google.srclib.dataset.StockRecordDataset;

/**
 * 
 * @author Yuyao Liang
 * 
 */
public class StockDataCollector extends Collector {
	public final String VERSION = Messages
			.getString("StockDataCollector.VERSION"); //$NON-NLS-1$

	private static String url;
	private static StockDataCollector instance = null;
	private static String aMask = "yyyy-mm-dd"; //$NON-NLS-1$
	private static String mask1 = "m/d/yyyy"; //$NON-NLS-1$
	private static SimpleDateFormat mydf;
	private static SimpleDateFormat df;

	public static StockDataCollector getInstance() {
		if (instance == null) {
			instance = new StockDataCollector();
			mydf = new SimpleDateFormat(aMask);
			df = new SimpleDateFormat(mask1);
		}
		return instance;
	}

	public String url(String str) throws MalformedURLException {
		URL myurl = new URL(str);
		BufferedReader in;
		try {
			in = new BufferedReader(new InputStreamReader(myurl.openStream()));
			url = in.readLine();
			in.close();
		} catch (IOException e) {
			System.out.println(Messages.getString("StockDataGetter.IOError")); //$NON-NLS-1$
		}
		return url;
	}

	private String getHistoryDataURL(String stock) {
		return "http://finance.yahoo.com/q/hp?s=" + stock; //$NON-NLS-1$
	}

	private String getHistoryDataDownloadURL(String url, String stock) {
		String result = null;
		String sstr = "http://ichart.finance.yahoo.com/table.csv?s="; //$NON-NLS-1$
		URL targetUrl;
		try {
			targetUrl = new URL(url);

			URLConnection targetUrlCon = targetUrl.openConnection();
			targetUrlCon.setDoOutput(true);
			BufferedReader in = new BufferedReader(new InputStreamReader(
					targetUrlCon.getInputStream()));
			while (true) {
				String line = in.readLine();
				if (line == null)
					break;
				if (line.contains(sstr)) {
					line = line
							.substring(line.indexOf(sstr), line.length() - 2);
					if (line.contains("\"><")) { //$NON-NLS-1$
						line = line.substring(0, line.indexOf("\"><")); //$NON-NLS-1$
					}
					result = line;
				}
			}
		} catch (Exception e) {
			System.out.println("ERROR: Malformed URL exception - " //$NON-NLS-1$
					+ e.getMessage());
		}

		return result;
	}

	@SuppressWarnings("deprecation")
	private String getCSVURL(String dateStr, String stock) {
		Date date = new Date();
		String s1 = "&d=" + date.getMonth() + "&e=" + date.getDate() + "&f=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				+ (date.getYear() + 1900);
		date = new Date(dateStr);
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DAY_OF_MONTH, 1);
		date = cal.getTime();
		String s2 = "&g=d&a=" + date.getMonth() + "&b=" + date.getDate() //$NON-NLS-1$ //$NON-NLS-2$
				+ "&c=" + (date.getYear() + 1900); //$NON-NLS-1$
		return "http://ichart.finance.yahoo.com/table.csv?s=" + stock + s1 + s2 //$NON-NLS-1$
				+ "&ignore=.csv"; //$NON-NLS-1$
	}

	private List<String[]> getConents(String url) {
		List<String[]> list = new ArrayList<String[]>();
		URL targetUrl;
		try {

			targetUrl = new URL(url);

			URLConnection targetUrlCon = targetUrl.openConnection();
			targetUrlCon.setDoOutput(true);
			BufferedReader in = new BufferedReader(new InputStreamReader(
					targetUrlCon.getInputStream()));
			while (true) {
				String line = in.readLine();
				if (line == null)
					break;
				list.add(parseDownloadCSV(line));
			}
		} catch (Exception e) {
			System.out.println("ERROR: Malformed URL exception - " //$NON-NLS-1$
					+ e.getMessage());
		}
		return list;
	}

	private String[] parseDownloadCSV(String line) {
		String[] values = line.split(","); //$NON-NLS-1$
		if (values[0].equalsIgnoreCase("Date")) { //$NON-NLS-1$
		} else {
			Date date;
			try {
				date = mydf.parse(values[0]);
				values[0] = df.format(date);
			} catch (ParseException pe) {
			}
		}
		return values;
	}

	protected String downloadFromGoogle(String stock) {
		String result = "http://finance.google.com/finance/historical?q=OTC:" //$NON-NLS-1$
				+ stock + "&output=csv"; //$NON-NLS-1$
		return result;
	}

	public StockRecordDataset getStockData(String stock, StockRecordDataset sd)
			throws SQLException {
		String url = getHistoryDataDownloadURL(getHistoryDataURL(stock), stock);
		if (sd.getCount() > 0) {
			String dateStr = getLatestDate(sd);
			url = getCSVURL(dateStr, stock);
		}
		List<String[]> list = getConents(url);
		for (int i = list.size() - 1; i > 0; i--) {
			Object[] o = list.get(i);
			sd.addRow(o);
		}
		return sd;
	}

	public StockRecordDataset getStockData(String stock, StockRecordDataset sd,
			String startDate) throws SQLException {
		String url = getCSVURL(startDate, stock);
		if (sd.getCount() > 0) {
			String dateStr = getLatestDate(sd);
			url = getCSVURL(dateStr, stock);
		}
		List<String[]> list = getConents(url);
		for (int i = list.size() - 1; i > 0; i--) {
			Object[] o = list.get(i);
			sd.addRow(o);
		}
		return sd;
	}

	private String getLatestDate(StockRecordDataset sd) throws SQLException {
		String dateStr = null;
		for (int i = 0; i < sd.getCount(); i++) {
			sd.next();
		}
		dateStr = sd.getString(1);
		return dateStr;
	}

	@Override
	public String getVersion() {
		return VERSION;
	}

}
